use crate::matrix::{Matrix, MatrixView, MatrixViewMut};
use crate::function::{dsigmoid, dtanh, sigmoid, tanh};

#[derive(Debug, Clone)]
pub struct Activation {
    active: fn(f64) -> f64,
    dactive: fn(f64) -> f64,
}

impl Activation {
    pub fn sigmoid() -> Self {
        Self { active: sigmoid, dactive: dsigmoid }
    }

    pub fn tanh() -> Self {
        Self { active: tanh, dactive: dtanh }
    }
}

impl Activation {
    pub fn active(&self, mat: MatrixView) -> Matrix {
        let mut res = Matrix::zeros(mat.size());
        for row in 0..res.row_size() {
            for col in 0..res.col_size() {
                res[(row, col)] = (self.active)(mat[(row, col)]);
            }
        }

        res
    }

    pub fn dactive(&self, mat: MatrixView) -> Matrix {
        let mut res = Matrix::zeros(mat.size());
        for row in 0..res.row_size() {
            for col in 0..res.col_size() {
                res[(row, col)] = (self.dactive)(mat[(row, col)]);
            }
        }

        res
    } 

    pub fn actived(&self, mut mat: MatrixViewMut) {
        for row in 0..mat.row_size() {
            for col in 0..mat.col_size() {
                let v = mat[(row, col)];
                mat[(row, col)] = (self.active)(v);
            }
        }
    }

    pub fn dactived(&self, mut mat: MatrixViewMut) {
        for row in 0..mat.row_size() {
            for col in 0..mat.col_size() {
                let v = mat[(row, col)];
                mat[(row, col)] = (self.dactive)(v);
            }
        }
    }
}
